<?php

// +----------------------------------------------------------------------
// | yogurt
// +----------------------------------------------------------------------
// +----------------------------------------------------------------------
// | Author: fengyi <1719847255.qq.com>
// +----------------------------------------------------------------------

namespace yogurt\file;


use yogurt\Yogurt;

class File extends Yogurt
{
    /**
     * 实例化属性
     * @var $_instance
     */
    public static $_instance;

    /**
     * 前端上传的文件
     * @var $_file
     */
    public static $_file;

    /**
     * 上传验证
     * @var $_validate
     */
    public static $_validate = [
        'size' => 0,
        'ext' => '',
        'type' => ''
    ];

    /**
     * 上传规则，默认md5，支持sha1，uniqid，urlencode等
     * @var $_rule
     */
    public static $_rule = 'md5';

    /**
     * 验证提示消息
     * @var array $_message
     */
    public static $_message = [
        'error' => 0,
        'msg' => ''
    ];

    /**
     * 上传文件的后缀信息
     * @var $_extInfo
     */
    public static $_extInfo;

    /**
     * 转换单位
     * @var int $_unit
     */
    public static $_unit = 1000;

    /**
     * 保存的文件
     * @var $_saveFileName
     */
    public static $_saveFileName;

    /**
     * 获取文件
     * @param $key
     * @return File
     */
    public static function get($key): File
    {
        if (!self::$_instance instanceof self) {
            self::$_instance = new self();
        }
        if (is_null(self::$_file)) {
            self::$_file = $_FILES[$key];
        }
        return self::$_instance;
    }

    /**
     * 验证上传
     * @param $validate
     * @return mixed
     */
    public function validate($validate)
    {
        self::$_validate = array_merge(self::$_validate, $validate);
        // 验证上传文件大小
        if (self::$_validate['size'] != 0 && ceil(self::$_file['size'] / self::$_unit) > self::$_validate['size']) {
            self::$_message = ['error' => '-1', 'msg' => 'The uploaded file is too large'];
        }
        // 验证上传文件类型
        if (self::$_validate['type'] != '' && self::$_validate['type'] != self::$_file['type']) {
            self::$_message = ['error' => '-1', 'msg' => 'The uploaded file type is not allowed'];
        }
        $fileInfo = self::getExt(self::$_file['name']);
        self::checkExtension($fileInfo);
        // 验证上传文件后缀
        if (self::$_validate['ext'] != '' && isset($fileInfo['extension']) && !in_array($fileInfo['extension'], explode(',', self::$_validate['ext']))) {
            self::$_message = ['error' => '-1', 'msg' => 'The uploaded file type is not allowed'];
        }
        return self::$_instance;
    }

    /**
     * 上传规则
     * @param $rule
     * @return mixed
     */
    public function rule($rule)
    {
        self::$_rule = $rule;
        return self::$_instance;
    }

    /**
     * 获取上传目录
     * @param $filePath
     * @return array|string|string[]
     */
    public static function getUploadPath($filePath)
    {
        $rule = self::$_rule;
        $upPath = $filePath . DIRECTORY_SEPARATOR . date('Y-m-d');
        self::directory($upPath);
        $upPath = $upPath . DIRECTORY_SEPARATOR . $rule(self::$_file['name']);
        return str_replace(array('//', '\\'), DIRECTORY_SEPARATOR, $upPath);
    }

    /**
     * 检测文件后缀
     * @param $fileInfo
     * @return array|string[]
     */
    public static function checkExtension($fileInfo): array
    {
        if (!isset($fileInfo['extension'])) {
            self::$_message = ['error' => '-1', 'msg' => 'The uploaded file type is not allowed'];
        }
        return self::$_message;
    }

    /**
     * 上传文件
     * @param $filePath
     * @return array|false
     */
    public function move($filePath)
    {
        $fileInfo = self::getExt(self::$_file['name']);
        self::checkExtension($fileInfo);
        if (self::$_message['error'] != 0) {
            return self::$_instance;
        }
        $upPath = self::getUploadPath($filePath);
        self::$_saveFileName = $upFile = $upPath . '.' . $fileInfo['extension'];
        if (self::$_message['error'] != 0) {
            return self::$_instance;
        }
        //移动文件
        if (!move_uploaded_file(self::$_file['tmp_name'], $upFile)) {
            self::$_message = ['error' => '-1', 'msg' => 'The file upload failed'];
        }
        return self::$_instance;
    }

    /**
     * 获取上传文件后缀
     * @param $path
     * @return array|string|string[]
     */
    public function getExt($path)
    {
        return self::$_extInfo = pathinfo(basename($path));
    }

    /**
     * 保存的文件
     * @return mixed
     */
    public function getSaveName()
    {
        return self::$_saveFileName;
    }

    /**
     * 文件上传错误信息
     * @return array
     */
    public function getError(): array
    {
        return self::$_message;
    }

    /**
     * 递归式创建目录
     * @param $dir
     * @return bool
     */
    public static function directory($dir): bool
    {
        return is_dir($dir) or self::directory(dirname($dir)) and mkdir($dir, 0777);
    }


    /**
     * 递归式删除目录
     * @param $dir
     * @return bool
     */
    public static function rm($dir): bool
    {
        $dir = realpath($dir);

        if (!is_dir($dir) || $dir == '/') {
            return false;
        }

        $handle = opendir($dir);
        while (false !== ($file = readdir($handle))) {
            if ($file == '.' || $file == '..') {
                continue;
            }
            if (is_dir($dir . '/' . $file)) {
                self::rm($dir . '/' . $file);
            } else {
                unlink($dir . '/' . $file);    //删除文件
            }
        }
        closedir($handle);      //关闭目录句柄
        if (basename($dir) != 'runtime') {
            rmdir($dir);           //删除空目录
        }
        return true;
    }

}
